package com.imxinxin.common.tools.http;

import com.imxinxin.common.tools.string.StringTool;
import lombok.SneakyThrows;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;


/**
 * @Author: XYX
 * @Date: 2019/4/2 21:15
 * @Description:
 **/
public class HostTool {


    public static final String x_forwarded_for = "X-Forwarded-For";

    public static String localIp;
    public static String localHostName;
    public static String outIp;


    static {
        localIp = localIp();
        localHostName = localHostName();

    }

    /**
     * 获取本机ip
     *
     * @return
     */
    public static String localIp() {
        try {
            localIp = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            localIp = "127.0.0.1";
        }
        return localIp;
    }

    /**
     * 获取本机域名
     *
     * @return
     */
    public static String localHostName() {
        InetAddress addr;
        try {
            addr = InetAddress.getLocalHost();
            localHostName = addr.getHostName();
        } catch (UnknownHostException e) {
            localHostName = "localhost";
        }
        return localHostName;
    }

    public static String getFormString(Map<Object, Object> params) {
        if (params == null || params.size() == 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<Object, Object> entry : params.entrySet()) {
            sb.append(entry.getKey());
            sb.append("=");
            sb.append(entry.getValue());
            sb.append("&");
        }
        return sb.toString();
    }


    public static String getFormStringUrlEncode(Map<Object, Object> params, String enc) {
        if (params == null || params.size() == 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<Object, Object> entry : params.entrySet()) {
            sb.append(entry.getKey());
            if (entry.getKey() == null || entry.getValue() == null) continue;
            try {
                sb.append(URLEncoder.encode(entry.getKey().toString(), enc));
                sb.append("=");
                sb.append(entry.getValue());
                sb.append(URLEncoder.encode(entry.getValue().toString(), enc));
                sb.append("&");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }

        }
        return sb.toString();
    }


    @SneakyThrows
    public static String getFormString(Object params, Class<?> clz, boolean isEncode, String enc) {
        if (params == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        Field[] fields = clz.getDeclaredFields();

        Object v;
        for (Field field : fields) {
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            field.setAccessible(true);
            v = field.get(params);
            if (v == null) {
                continue;
            }
            sb.append(isEncode ? URLEncoder.encode(field.getName(), enc) : field.getName());
            sb.append("=");
            sb.append(isEncode ? URLEncoder.encode(v.toString(), enc) : v.toString());

            sb.append("&");
        }

        if (clz.getSuperclass() == Object.class) {
            return sb.toString();
        }

        return sb.append(getFormString(params, clz.getSuperclass(), isEncode, enc)).toString();

    }

    public static String getFormString(Object params) {
        return getFormString(params, params.getClass(), false, null);
    }

    /**
     * 根据url获取参数
     *
     * @param url 带参数的url
     * @return 参数map
     */
    public static Map<String, String> getParams(String url) {

        if (StringTool.isEmpty(url)) return null;

        int i = url.indexOf("?") + 1;

        if (i == 0 || i == url.length()) return null;

        int j = url.indexOf("#");

        if (i > j && j != -1) return null;
        else j = url.length();

        String[] urls = url.substring(i, j).split("&");
        Map<String, String> map = new HashMap<>();
        String[] param;
        for (i = 0; i < urls.length; i++) {
            if (StringTool.isEmpty(urls[i]) || !urls[i].contains("=")) {
                continue;
            }
            param = urls[i].split("=");
            if (param.length != 2) {
                map.put(param[0], "");
            }
            map.put(param[0], param[1]);
        }
        return map.size() == 0 ? null : map;
    }

    /**
     * 根据url获取domain
     *
     * @param url
     * @return
     */
    public static String getDomain(String url) {
        if (StringTool.isEmpty(url)) return url;
        int i = url.indexOf("?");
        int j = url.indexOf("#");
        int min;
        int max;
        if (i < j) {
            min = i;
            max = j;
        } else {
            min = j;
            max = i;
        }
        if (min != -1) {
            return url.substring(0, min);
        }
        if (max != -1) {
            return url.substring(0, max);
        }
        return url;
    }

//
//    /**
//     * 获取自己的公网ip
//     *
//     * @return
//     */
//    public static String outIp() {
//        String html = null;
//        try {
//            html = HttpSend.httpRequestUrlencoded("https://ip.cn", null, "GET");
//        } catch (IOException e) {
//            e.printStackTrace();
//            return localIp;
//        }
//
//        Document doc = Jsoup.parse(html);
//        Element e = doc.body().getElementById("result");
//        Element e1 = e.child(0).child(0);
//        Node n1 = e1.childNode(1);
//        Node n2 = n1.childNode(0);
//        return n2.toString();
//    }


    /**
     * 根据request获取客户端ip
     */
    public static String getClientIp(String forwarded) {
        int i = forwarded.indexOf(",");

        String s;
        if (i == -1) {
            s = forwarded;
        } else {
            s = forwarded.substring(0, i);
        }

//        if (s.length() > 128) {
//            String log = "客户端伪造ip" + x_forwarded_for + ":" + forwarded;
//            RuntimeException runtimeException = new RuntimeException(log);
//            XLogger.error("客户端伪造ip", runtimeException);
//            throw runtimeException;
//        }
        return s;
    }


    public static final String _255 = "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
    public static final Pattern pattern = Pattern.compile("^(?:" + _255 + "\\.){3}" + _255 + "$");

    public static String longToIpV4(long longIp) {
        int octet3 = (int) ((longIp >> 24) % 256);
        int octet2 = (int) ((longIp >> 16) % 256);
        int octet1 = (int) ((longIp >> 8) % 256);
        int octet0 = (int) ((longIp) % 256);
        return octet3 + "." + octet2 + "." + octet1 + "." + octet0;
    }

    public static long ipV4ToLong(String ip) {
        String[] octets = ip.split("\\.");
        return (Long.parseLong(octets[0]) << 24) + ((long) Integer.parseInt(octets[1]) << 16)
                + ((long) Integer.parseInt(octets[2]) << 8) + Integer.parseInt(octets[3]);
    }

    public static boolean isIPv4Private(String ip) {
        long longIp = ipV4ToLong(ip);
        return (longIp >= ipV4ToLong("10.0.0.0") && longIp <= ipV4ToLong("10.255.255.255"))
                || (longIp >= ipV4ToLong("172.16.0.0") && longIp <= ipV4ToLong("172.31.255.255"))
                || longIp >= ipV4ToLong("192.168.0.0") && longIp <= ipV4ToLong("192.168.255.255");
    }

    public static boolean isIPv4Valid(String ip) {
        return pattern.matcher(ip).matches();
    }


}
